package com.jiegui.socket;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.HexUtil;
import com.jiegui.common.utils.DateUtils;
import com.jiegui.common.utils.StringUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.text.DateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @description:
 * @author: wuqicheng
 * @time: 14/2/2023 下午 4:32
 */
@Data
@Slf4j
public class ClientSocket implements Runnable {
    private static final Logger logger = LoggerFactory.getLogger("file-socket");

    private Socket socket;
    private DataInputStream inputStream;
    private DataOutputStream outputStream;
    private String key;
    private String message;

    /**
     * 注册socket到map里
     *
     * @param socket
     * @return
     */
    public static ClientSocket register(Socket socket, int count) throws Exception {
        ClientSocket client = new ClientSocket();
        try {
            client.setSocket(socket);
            client.setInputStream(new DataInputStream(socket.getInputStream()));
            client.setOutputStream(new DataOutputStream(socket.getOutputStream()));
            logger.info("客户端的IP：" + socket.getInetAddress().getHostAddress() + "正在登录...");
            client.setKey(socket.getInetAddress().getHostAddress());
            DelongServerSocket.clientsMap.put(client.getKey(), client);
            System.out.println(DelongServerSocket.clientsMap);

            DelongServerSocket.ipMap.put(socket.getInetAddress().getHostAddress(),new Date());
            //每次有设备链接则进行一次链接清理 1710984130577
            try{
                for (Map.Entry<String, Date> entry : DelongServerSocket.ipMap.entrySet()) {
                    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
                    Date time=entry.getValue();
                    System.out.println(DateUtil.format(time, DateUtils.YYYY_MM_DD_HH_MM_SS));
                    //如果链接超过3分钟没有通信则剔除该链接
                    if(DateUtils.addMinutes(time,3).before(new Date())){
                        client.logout(entry.getKey());
                        log.info("----------剔除未通信的连接{}",entry.getKey());
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            return client;
        } catch (Exception e) {
            client.logout();
        }
        return null;
    }

    /**
     * 发送数据
     *
     * @param str
     */
    public void send(String str) throws Exception {
        logger.info("服务端发送:======" + str);
        try {
            outputStream.write(str.getBytes());
        } catch (Exception e) {
            logout();
        }
    }

    /**
     * 接收数据
     *
     * @return
     * @throws Exception
     */
    public String receive() throws Exception {
        try {
            if (socket == null) {
                return null;
            }
            byte[] bytes = new byte[socket.getInputStream().available()];

            socket.getInputStream().read(bytes);
            String receive = HexUtil.encodeHexStr(bytes).replaceAll("(.{2})", "$1 ");
            if (!StringUtils.isEmpty(receive)) {
                DelongServerSocket.ipMap.put(socket.getInetAddress().getHostAddress(),new Date());
                SocketReadUtil.distribute(receive, socket.getInetAddress().getHostAddress());

            }

            return receive;
        } catch (Exception e) {
            e.printStackTrace();
            // logout();
        }
        return null;
    }

    /**
     * 登出操作, 关闭各种流
     */
    public void logout() throws Exception {
        if (DelongServerSocket.clientsMap.containsKey(key)) {
            DelongServerSocket.clientsMap.remove(key);
        }
        DelongServerSocket.ipMap.remove(key);
        logger.info ("-----------:"+DelongServerSocket.clientsMap.toString());
        try {
//            socket.shutdownOutput();
//            socket.shutdownInput();
         //   inputStream.close();
         //   outputStream.close();
        } catch (Exception e) {
            throw new Exception("关闭输入输出异常", e);
        } finally {
//            try {
//                socket.close();
//            } catch (Exception e) {
//                throw new Exception("关闭socket异常", e);
//            }
        }
    }

    /**
     * 登出操作, 关闭各种流
     */
    public void logout(String value) throws Exception {
        if (DelongServerSocket.clientsMap.containsKey(value)) {
            DelongServerSocket.clientsMap.remove(value);
        }
        DelongServerSocket.ipMap.remove(key);
        logger.info ("-----------:"+DelongServerSocket.clientsMap.toString());
        try {
//            socket.shutdownOutput();
//            socket.shutdownInput();
          //  inputStream.close();
        //    outputStream.close();
        } catch (Exception e) {
            throw new Exception("关闭输入输出异常", e);
        } finally {
//            try {
//                socket.close();
//            } catch (Exception e) {
//                throw new Exception("关闭socket异常", e);
//            }
        }
    }

    /**
     * 发送数据包, 判断数据连接状态
     *
     * @return
     */
    public boolean isSocketClosed() {
        try {
            //socket.sendUrgentData(1);
            //发送
//            Socket socket1 = DelongServerSocket.clientsMap.get("user1").getSocket();
//            socket1.getOutputStream().write("测试1".getBytes(StandardCharsets.UTF_8));
            //socket.getOutputStream().write("测试".getBytes(StandardCharsets.UTF_8));
            //接收
            byte[] bytes = new byte[1024];
            socket.getInputStream().read(bytes);
            String receive = HexUtil.encodeHexStr(bytes);


            logger.info("服务端接收消息" + receive);
            return false;
        } catch (Exception e) {
            return true;
        }
    }

    @Override
    public void run() {
//        // 每过5秒连接一次客户端
        while (true) {
            try {
                TimeUnit.MILLISECONDS.sleep(100);
                receive();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }

    @Override
    public String toString() {
        return "Client{" +
                "socket=" + socket +
                ", inputStream=" + inputStream +
                ", outputStream=" + outputStream +
                ", key='" + key + '\'' +
                '}';
    }


}
